// VisaApiDemoDlg.cpp : implementation file
//

#include "stdafx.h"
#include "VisaApiDemo.h"

#include "VisaAttributeMetadata.h"
#include "VisaAttributeExplorer.h"
#include "VisaApiDemoDlg.h"

#include "EventHooks.h"



#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};


CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}


void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CVisaApiDemoDlg dialog

CVisaApiDemoDlg::CVisaApiDemoDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CVisaApiDemoDlg::IDD, pParent),
	m_pobjAttribExplorer(NULL)
{
	//{{AFX_DATA_INIT(CVisaApiDemoDlg)
	m_strResourceName = _T("GPIB8::1::INSTR");
	m_bExclusiveLock = FALSE;
	m_bLoadConfig = FALSE;
	m_dwTimeout = 0;
	m_strTestParameter = _T("*idn?\r\n");
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

	// VISA specific stuff
	m_stat = VI_SUCCESS;
	m_viDefRM = m_viSession = VI_NULL;
	m_idJob = 0;
	m_bIOComplete = false;
}

void CVisaApiDemoDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CVisaApiDemoDlg)
	DDX_Control(pDX, IDC_PARSE_RSRC, m_btnParseRsrc);
	DDX_Control(pDX, IDC_FIND_RSRC, m_btnFindRsrc);
	DDX_Control(pDX, IDC_VI_CLEAR, m_btnClear);
	DDX_Control(pDX, IDC_VI_READ_ASYNC, m_btnReadAsync);
	DDX_Control(pDX, IDC_VI_WRITE_ASYNC, m_btnWriteAsync);
	DDX_Control(pDX, IDC_VI_READ, m_btnRead);
	DDX_Control(pDX, IDC_VI_WRITE, m_btnWrite);
	DDX_Control(pDX, IDC_ATTRIBUTES, m_btnAttributes);
	DDX_Control(pDX, IDC_EVENT_IO_COMPLETE, m_btnIOComplete);
	DDX_Control(pDX, IDC_VI_STATUS, m_editViStatus);
	DDX_Control(pDX, IDC_RESULT_INFO, m_mleInfo);
	DDX_Control(pDX, IDC_OPEN_CLOSE, m_btnOpenClose);
	DDX_Control(pDX, IDC_OPEN_CLOSE_DEF_RM, m_btnOpenCloseDefRM);
	DDX_Text(pDX, IDC_OPEN_RESOURCE_NAME, m_strResourceName);
	DDX_Check(pDX, IDC_VI_EXCLUSIVE_LOCK, m_bExclusiveLock);
	DDX_Check(pDX, IDC_VI_LOAD_CONFIG, m_bLoadConfig);
	DDX_Text(pDX, IDC_TIMEOUT, m_dwTimeout);
	DDX_Text(pDX, IDC_TEST_PARAMETER, m_strTestParameter);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CVisaApiDemoDlg, CDialog)
	//{{AFX_MSG_MAP(CVisaApiDemoDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_OPEN_CLOSE_DEF_RM, OnOpenCloseDefRm)
	ON_BN_CLICKED(IDC_OPEN_CLOSE, OnOpenClose)
	ON_BN_CLICKED(IDC_PARSE_RSRC, OnParseRsrc)
	ON_BN_CLICKED(IDC_VI_WRITE, OnViWrite)
	ON_BN_CLICKED(IDC_VI_READ, OnViRead)
	ON_BN_CLICKED(IDC_FIND_RSRC, OnFindRsrc)
	ON_BN_CLICKED(IDC_VI_WRITE_ASYNC, OnViWriteAsync)
	ON_BN_CLICKED(IDC_VI_READ_ASYNC, OnViReadAsync)
	ON_BN_CLICKED(IDC_EVENT_IO_COMPLETE, OnEventIoCompleteCallback)
	ON_BN_CLICKED(IDC_ATTRIBUTES, OnAttributes)
	ON_BN_CLICKED(IDC_VI_CLEAR, OnViClear)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()



/////////////////////////////////////////////////////////////////////////////
// CVisaApiDemoDlg helper methods

//// CVisaApiDemoDlg::UpdateStatus
//
// Update text in IDC_VI_STATUS read-only edit control.  Usually called after
// VISA operator invoked.
//
void
CVisaApiDemoDlg::UpdateStatus()
{
	if (m_stat == VI_SUCCESS)
	{
		m_editViStatus.SetWindowText(_T("VI_SUCCESS"));
	}
	else
	{
		CString strViStatus;
		ViChar szError[VI_FIND_BUFLEN * 2];
		szError[0] = '\0';

		if (m_viSession != VI_NULL)
		{
			viStatusDesc(m_viSession, m_stat, szError);
		}
		else if (m_viDefRM != VI_NULL)
		{
			viStatusDesc(m_viDefRM, m_stat, szError);
		}
		if (szError[0] != '\0')
		{
			strViStatus.Format(_T("%d / %#x\r\n%s"), m_stat, m_stat, szError);
		}
		else
		{
			strViStatus.Format(_T("%d / %#x"), m_stat, m_stat);
		}
		m_editViStatus.SetWindowText(strViStatus);
	}
}


//// CVisaApiDemoDlg::UpdateButtons
//
// Update label of command buttons to indicate latest state (e.g. session
// open / closed).
//
void
CVisaApiDemoDlg::UpdateButtons()
{
	if (m_viDefRM == VI_NULL)
	{
		m_btnOpenCloseDefRM.SetWindowText(_T("viOpenDefaultRM()"));
	}
	else
	{
		m_btnOpenCloseDefRM.SetWindowText(_T("viClose(<default-session>)"));
	}
	if (m_viSession == VI_NULL)
	{
		m_btnOpenClose.SetWindowText(_T("viOpen(<vi-session>)"));
	}
	else
	{
		m_btnOpenClose.SetWindowText(_T("viClose(<vi-session>)"));
	}
	if (m_bIOComplete)
	{
		m_btnIOComplete.SetWindowText(_T("disable I/O completion callback"));
	}
	else
	{
		m_btnIOComplete.SetWindowText(_T("enable I/O completion callback"));
	}
	if (m_viDefRM != VI_NULL)
	{
		m_btnFindRsrc.EnableWindow(TRUE);
		m_btnParseRsrc.EnableWindow(TRUE);
	}
	else
	{
		m_btnFindRsrc.EnableWindow(FALSE);
		m_btnParseRsrc.EnableWindow(FALSE);
	}
	if (m_viSession != VI_NULL)
	{
		m_btnAttributes.EnableWindow(TRUE);
		m_btnWrite.EnableWindow(TRUE);
		m_btnRead.EnableWindow(TRUE);
		m_btnWriteAsync.EnableWindow(TRUE);
		m_btnReadAsync.EnableWindow(TRUE);
		m_btnIOComplete.EnableWindow(TRUE);
		m_btnClear.EnableWindow(TRUE);
	}
	else
	{
		m_btnAttributes.EnableWindow(FALSE);
		m_btnWrite.EnableWindow(FALSE);
		m_btnRead.EnableWindow(FALSE);
		m_btnWriteAsync.EnableWindow(FALSE);
		m_btnReadAsync.EnableWindow(FALSE);
		m_btnIOComplete.EnableWindow(FALSE);
		m_btnClear.EnableWindow(FALSE);
	}

	UpdateStatus();
}


//// CVisaApiDemoDlg::Wait4IOCompletion
//
// Handle I/O completion event.
//
void
CVisaApiDemoDlg::Wait4IOCompletion(
	ViPUInt32 pcbIO
)
{
	ViEventType idActualEvent = 0;
	ViEvent context = VI_NULL;
	m_stat = viWaitOnEvent(m_viSession, VI_EVENT_IO_COMPLETION, 2000, &idActualEvent, &context);
	if (m_stat >= VI_SUCCESS)
	{
		if (pcbIO != NULL)
		{
			viGetAttribute(context, VI_ATTR_RET_COUNT, pcbIO);
		}
		viClose(context);
	}
}


//// CVisaApiDemoDlg::PeakMessages
//
// Pump UI messages so dialog will update within command handler method.
//
void
CVisaApiDemoDlg::PeakMessages()
{
	MSG msg;	
	while (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
	{
		if (msg.message == WM_QUIT)
		{
			::PostQuitMessage(msg.wParam);
			break;
		}

		::TranslateMessage(&msg);
		::DispatchMessage(&msg);
	}
}


//// CVisaApiDemoDlg::AttributeExplorerClosing
//
// Handle close of modeless attribute dialog.
//
void
CVisaApiDemoDlg::AttributeExplorerClosing()
{
	m_pobjAttribExplorer = NULL;
	UpdateButtons();
}


//// CVisaApiDemoDlg::GetVisaAttribute
//
//
//
bool
CVisaApiDemoDlg::GetVisaAttribute(
	ViAttr attribute,
	void* attrState
)
{
	m_editViStatus.SetWindowText("");
	m_mleInfo.SetWindowText("");
	PeakMessages();

	if (m_viSession != VI_NULL)
	{
		m_stat = viGetAttribute(m_viSession, attribute, attrState);
		UpdateStatus();
		return (m_stat >= VI_SUCCESS) ? true : false;
	}
	else
	{
		m_editViStatus.SetWindowText(_T("Session not open!"));
		return false;
	}
}


//// CVisaApiDemoDlg::SetVisaAttribute
//
//
//
void
CVisaApiDemoDlg::SetVisaAttribute(
	ViAttr attribute,
	ViAttrState attrState
)
{
	m_editViStatus.SetWindowText("");
	m_mleInfo.SetWindowText("");
	PeakMessages();

	if (m_viSession != VI_NULL)
	{
		m_stat = viSetAttribute(m_viSession, attribute, attrState);
		UpdateStatus();
	}
	else
	{
		m_editViStatus.SetWindowText(_T("Session not open!"));
	}
}



/////////////////////////////////////////////////////////////////////////////
// CVisaApiDemoDlg message handlers

BOOL CVisaApiDemoDlg::OnInitDialog()
{
	CDialog::OnInitDialog();
	g_hFocusWindow = m_hWnd;

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here
	
	return TRUE;  // return TRUE  unless you set the focus to a control
}


void CVisaApiDemoDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}


// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CVisaApiDemoDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}


// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CVisaApiDemoDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}


//// CVisaApiDemoDlg::OnOpenCloseDefRm
//
// Command button handler for "viOpenDefaultRM() / viClose(<default-session>)" button.
//
void CVisaApiDemoDlg::OnOpenCloseDefRm() 
{
	m_editViStatus.SetWindowText("");
	m_mleInfo.SetWindowText("");
	PeakMessages();

	if (m_viDefRM == VI_NULL)
	{
		m_stat = viOpenDefaultRM(&m_viDefRM);
	}
	else
	{
		m_stat = viClose(m_viDefRM);
		m_viDefRM = VI_NULL;
		m_viSession = VI_NULL;
		m_bIOComplete = false;
	}
	UpdateButtons();
}


//// CVisaApiDemoDlg::OnFindRsrc
//
// Command button handler for "viFindRsrc()" button.
//
void CVisaApiDemoDlg::OnFindRsrc() 
{
	m_editViStatus.SetWindowText("");
	m_mleInfo.SetWindowText("");
	PeakMessages();

	if (m_viDefRM == VI_NULL)
	{
		m_stat = viOpenDefaultRM(&m_viDefRM);
		if (m_stat != VI_SUCCESS)
		{
			UpdateButtons();
			return;
		}
	}
	UpdateData();

	ViFindList fl = NULL;
	ViUInt32 nMatches = 0;
	ViChar szResourceName[VI_FIND_BUFLEN];
	m_stat = viFindRsrc(m_viDefRM, (LPSTR)((LPCSTR)m_strResourceName),
		&fl, &nMatches, szResourceName);
	CString strRsrcList;
	if (m_stat == VI_SUCCESS)
	{
		strRsrcList += szResourceName;
		strRsrcList += _T("\r\n");
	}

	if (fl != NULL)
	{
		for (ViUInt32 i = 1; (m_stat == VI_SUCCESS) && (i < nMatches); ++i)
		{
			m_stat =  viFindNext(fl, szResourceName);
			if (m_stat == VI_SUCCESS)
			{
				strRsrcList += szResourceName;
				strRsrcList += _T("\r\n");
			}
		}

		viClose(fl);
	}

	if (strRsrcList.GetLength() > 0)
	{
		m_mleInfo.SetWindowText(strRsrcList);
	}

	UpdateButtons();
}


//// CVisaApiDemoDlg::OnParseRsrc
//
// Command button handler for "viParseRsrc()" button.
//
void CVisaApiDemoDlg::OnParseRsrc() 
{
	m_editViStatus.SetWindowText("");
	m_mleInfo.SetWindowText("");
	PeakMessages();

	if (m_viDefRM == VI_NULL)
	{
		m_stat = viOpenDefaultRM(&m_viDefRM);
		if (m_stat != VI_SUCCESS)
		{
			UpdateButtons();
			return;
		}
	}
	UpdateData();
	ViUInt16 fInterfaceType = 0;
	ViUInt16 idBoard = 0;
	m_stat = viParseRsrc(m_viDefRM, (LPSTR)((LPCSTR)m_strResourceName), &fInterfaceType, &idBoard);

	if (m_stat == VI_SUCCESS)
	{
		CString strResult;
		strResult.Format(_T("intfType = %d\r\nintfNum = %d"), fInterfaceType, idBoard);
		m_mleInfo.SetWindowText(strResult);
	}

	UpdateButtons();
}


//// CVisaApiDemoDlg::OnOpenClose
//
// Command button handler for "viOpen(<vi-session>) / viClose(<vi-session>)" button.
//
void CVisaApiDemoDlg::OnOpenClose() 
{
	UpdateData();

	m_editViStatus.SetWindowText("");
	m_mleInfo.SetWindowText("");
	PeakMessages();

	if (m_viSession == VI_NULL)
	{
		if (m_viDefRM == VI_NULL)
		{
			m_stat = viOpenDefaultRM(&m_viDefRM);
			if (m_stat != VI_SUCCESS)
			{
				UpdateButtons();
				return;
			}
		}

		ViUInt32 fAccessMode = 0;
		if (m_bExclusiveLock)
		{
			fAccessMode |= VI_EXCLUSIVE_LOCK;
		}
		if (m_bLoadConfig)
		{
			fAccessMode |= VI_LOAD_CONFIG;
		}
		m_stat = viOpen(m_viDefRM, (LPSTR)((LPCSTR)m_strResourceName), fAccessMode, m_dwTimeout, &m_viSession);
	}
	else
	{
		m_stat = viClose(m_viSession);
		m_viSession = VI_NULL;
		m_bIOComplete = false;
	}

	UpdateButtons();
}


//// CVisaApiDemoDlg::OnAttributes
//
// Command button handler for "viGetAttribute / viSetAttribute..." button.
//
void CVisaApiDemoDlg::OnAttributes() 
{
	m_editViStatus.SetWindowText("");
	m_mleInfo.SetWindowText("");
	PeakMessages();

	if (m_pobjAttribExplorer == NULL)
	{
		m_pobjAttribExplorer = new CVisaAttributeExplorer(this);
        if (m_pobjAttribExplorer != NULL)
		{
            m_pobjAttribExplorer->Create();
		}
	}
	else
	{
		m_pobjAttribExplorer->RestoreDialog();
	}

	UpdateButtons();
}


//// CVisaApiDemoDlg::OnViWrite
//
// Command button handler for "viWrite()" button.
//
void CVisaApiDemoDlg::OnViWrite() 
{
	m_editViStatus.SetWindowText("");
	m_mleInfo.SetWindowText("");
	PeakMessages();

	if (m_viSession != VI_NULL)
	{
		UpdateData();
		ViUInt32 cbWritten = 0;
		m_stat = viWrite(m_viSession, (ViBuf)((LPCSTR)m_strTestParameter), m_strTestParameter.GetLength() * sizeof(TCHAR), &cbWritten);
		if (m_stat == VI_SUCCESS)
		{
			CString strResult;
			strResult.Format(_T("VI_SUCCESS\r\ncbWritten = %u"), cbWritten);
			m_editViStatus.SetWindowText(strResult);
		}
		else
		{
			UpdateButtons();
		}
	}
	else
	{
		m_editViStatus.SetWindowText(_T("Session not open!"));
	}
}


//// CVisaApiDemoDlg::OnViRead
//
// Command button handler for "viRead()" button.
//
void CVisaApiDemoDlg::OnViRead() 
{
	m_editViStatus.SetWindowText("");
	m_mleInfo.SetWindowText("");
	PeakMessages();

	if (m_viSession != VI_NULL)
	{
		TCHAR szReadBuf[(MAX_PATH * 8) + 1];
		ViUInt32 cbRead = 0;
		m_stat = viRead(m_viSession, (ViBuf)szReadBuf, sizeof(szReadBuf) - sizeof(TCHAR), &cbRead);
		if (m_stat >= VI_SUCCESS)
		{
			CString strResult;
			strResult.Format(_T("VI_SUCCESS (%#x)\r\ncbRead = %u"), m_stat, cbRead);
			m_editViStatus.SetWindowText(strResult);
			//
			// An additional byte may get written beyond cbRead bytes.  This
			// been observed with hardware GPIB interfaces.  Therefore, zeroing
			// szReadBuf[] before calling viRead() is not reliable.
			//
			szReadBuf[cbRead] = _T('\0');
			m_mleInfo.SetWindowText(szReadBuf);
		}
		else
		{
			UpdateButtons();
		}
	}
	else
	{
		m_editViStatus.SetWindowText(_T("Session not open!"));
	}
}


//// CVisaApiDemoDlg::OnViWriteAsync
//
// Command button handler for "viWriteAsync()" button.
//
void CVisaApiDemoDlg::OnViWriteAsync() 
{
	m_editViStatus.SetWindowText("");
	m_mleInfo.SetWindowText("");
	PeakMessages();

	if (m_viSession != VI_NULL)
	{
		UpdateData();
		m_stat = viSetAttribute(m_viSession, VI_ATTR_TMO_VALUE, (ViUInt32) 2000);	// 2 seconds
		if (m_stat != VI_SUCCESS)
		{
			UpdateStatus();
			return;
		}
		m_stat = viEnableEvent(m_viSession, VI_EVENT_IO_COMPLETION, VI_QUEUE, VI_NULL);
		if (m_stat != VI_SUCCESS)
		{
			UpdateStatus();
			viSetAttribute(m_viSession, VI_ATTR_TMO_VALUE, (ViUInt32) VI_TMO_INFINITE);
			return;
		}
		m_stat = viWriteAsync(m_viSession, (ViBuf)((LPCSTR)m_strTestParameter), m_strTestParameter.GetLength() * sizeof(TCHAR), &m_idJob);
		if (m_stat < VI_SUCCESS)
		{
			UpdateStatus();
			viDisableEvent(m_viSession, VI_EVENT_IO_COMPLETION, VI_QUEUE);
			viSetAttribute(m_viSession, VI_ATTR_TMO_VALUE, (ViUInt32) VI_TMO_INFINITE);
			return;
		}
		Wait4IOCompletion();
		if (m_stat < VI_SUCCESS)
		{
			UpdateStatus();
			viDisableEvent(m_viSession, VI_EVENT_IO_COMPLETION, VI_QUEUE);
			viSetAttribute(m_viSession, VI_ATTR_TMO_VALUE, (ViUInt32) VI_TMO_INFINITE);
			return;
		}

		m_stat = viDisableEvent(m_viSession, VI_EVENT_IO_COMPLETION, VI_QUEUE);
		m_stat = viSetAttribute(m_viSession, VI_ATTR_TMO_VALUE, (ViUInt32) VI_TMO_INFINITE);
		UpdateStatus();
	}
	else
	{
		m_editViStatus.SetWindowText(_T("Session not open!"));
	}
}


//// CVisaApiDemoDlg::OnViReadAsync
//
// Command button handler for "viReadAsync()" button.
//
void CVisaApiDemoDlg::OnViReadAsync() 
{
	m_editViStatus.SetWindowText("");
	m_mleInfo.SetWindowText("");
	PeakMessages();

	if (m_viSession != VI_NULL)
	{
		m_stat = viSetAttribute(m_viSession, VI_ATTR_TMO_VALUE, (ViUInt32) 2000);	// 2 seconds
		if (m_stat != VI_SUCCESS)
		{
			UpdateStatus();
			return;
		}
		m_stat = viEnableEvent(m_viSession, VI_EVENT_IO_COMPLETION, VI_QUEUE, VI_NULL);
		if (m_stat != VI_SUCCESS)
		{
			UpdateStatus();
			viSetAttribute(m_viSession, VI_ATTR_TMO_VALUE, (ViUInt32) VI_TMO_INFINITE);
			return;
		}
		TCHAR szReadBuf[(MAX_PATH * 8) + 1];
		memset(szReadBuf, 0, sizeof(szReadBuf));
		m_stat = viReadAsync(m_viSession, (ViBuf)szReadBuf, sizeof(szReadBuf) - sizeof(TCHAR), &m_idJob);
		if (m_stat < VI_SUCCESS)
		{
			UpdateStatus();
			viDisableEvent(m_viSession, VI_EVENT_IO_COMPLETION, VI_QUEUE);
			viSetAttribute(m_viSession, VI_ATTR_TMO_VALUE, (ViUInt32) VI_TMO_INFINITE);
			return;
		}
		ViUInt32 cbRead = 0;
		Wait4IOCompletion(&cbRead);
		if (m_stat >= VI_SUCCESS)
		{
			CString strResult;
			strResult.Format(_T("VI_SUCCESS (%#x)\r\ncbRead = %u"), m_stat, cbRead);
			m_editViStatus.SetWindowText(strResult);
			if (m_bIOComplete == false)
			{
				szReadBuf[cbRead] = _T('\0');
			}
			m_mleInfo.SetWindowText(szReadBuf);
			PeakMessages();
		}
		else
		{
			UpdateStatus();
			viDisableEvent(m_viSession, VI_EVENT_IO_COMPLETION, VI_QUEUE);
			viSetAttribute(m_viSession, VI_ATTR_TMO_VALUE, (ViUInt32) VI_TMO_INFINITE);
			return;
		}
		m_stat = viDisableEvent(m_viSession, VI_EVENT_IO_COMPLETION, VI_QUEUE);
		m_stat = viSetAttribute(m_viSession, VI_ATTR_TMO_VALUE, (ViUInt32) VI_TMO_INFINITE);
	}
	else
	{
		m_editViStatus.SetWindowText(_T("Session not open!"));
	}
}


//// CVisaApiDemoDlg::OnEventIoCompleteCallback
//
// Command button handler for "enable I/O completion callback" button.
//
void CVisaApiDemoDlg::OnEventIoCompleteCallback() 
{
	m_editViStatus.SetWindowText("");
	m_mleInfo.SetWindowText("");
	PeakMessages();

	if (m_viSession != VI_NULL)
	{
		if (m_bIOComplete)
		{
			m_bIOComplete = false;
			m_stat = viDisableEvent(m_viSession, VI_EVENT_IO_COMPLETION, VI_HNDLR);
			viUninstallHandler(m_viSession, VI_EVENT_IO_COMPLETION, EventHandlerIOComplete, VI_NULL);
		}
		else
		{
			m_stat = viInstallHandler(m_viSession, VI_EVENT_IO_COMPLETION, EventHandlerIOComplete, VI_NULL);
			if (m_stat == VI_SUCCESS)
			{
				m_stat = viEnableEvent(m_viSession, VI_EVENT_IO_COMPLETION, VI_HNDLR, VI_NULL);
			}
			if (m_stat == VI_SUCCESS)
			{
				m_bIOComplete = true;
			}
		}
		UpdateButtons();
	}
	else
	{
		m_editViStatus.SetWindowText(_T("Session not open!"));
	}
}


//// CVisaApiDemoDlg::OnViClear
//
// Command button handler for "viClear()" button.
//
void CVisaApiDemoDlg::OnViClear() 
{
	m_editViStatus.SetWindowText("");
	m_mleInfo.SetWindowText("");
	PeakMessages();

	if (m_viSession != VI_NULL)
	{
		m_stat = viClear(m_viSession);
		UpdateStatus();
	}
	else
	{
		m_editViStatus.SetWindowText(_T("Session not open!"));
	}
}
